package com.own.demo.writerfile;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.own.demo.utils.CommWriterFileInfo;
import com.own.demo.utils.DateUtils;
import com.own.demo.utils.FileToStringUtils;
import com.own.demo.vo.Bounds;
import com.own.demo.vo.NodeInfo;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;

import java.awt.image.ImageProducer;
import java.io.BufferedWriter;
import java.io.File;
import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicLong;

public class 油管项目OsmXMLV4 {
    private static AtomicLong indexNum = new AtomicLong(1);
    private static Map<String, NodeInfo> lonLatMap;
    static String geoOSMUrl = "D:\\dkSpace\\油库规划\\路网\\";
    static String geoOSMName = "all-水路和铁路-20250702163244.osm";

    public static void main(String[] args) {

        String jsonPath = "D:\\dkSpace\\油库规划\\铁路和水路.geojson";
        String data = FileToStringUtils.txt2String(new File(jsonPath));
        JSONObject geoJson = JSONObject.parseObject(data);


        List<Double> lonList = new ArrayList<>(1000000);
        List<Double> latList = new ArrayList<>(1000000);

        JSONArray jsonArray = geoJson.getJSONArray("features");
        System.out.println(jsonArray.size());

        for (int i = 0; i < jsonArray.size(); i++) {
            JSONArray jsonObject = jsonArray.getJSONObject(i).getJSONObject("geometry").getJSONArray("coordinates");
            for (int j = 0; j < jsonObject.size(); j++) {
                JSONArray jsonArray1 = jsonObject.getJSONArray(j);
                for (int k = 0; k < jsonArray1.size(); k++) {
                    JSONArray jsonArray2 = jsonArray1.getJSONArray(k);
                    lonList.add(jsonArray2.getDouble(0));
                    latList.add(jsonArray2.getDouble(1));
                }
            }
        }

        double minLon = Collections.min(lonList);
        double maxLon = Collections.max(lonList);
        double minLat = Collections.min(latList);
        double maxLat = Collections.max(latList);
        Bounds bounds = new Bounds(minLon, maxLon, minLat, maxLat);
        jsonToXML(geoJson, bounds, geoOSMUrl, geoOSMName);


        System.exit(-1);
    }

    public static void jsonToXML(JSONObject geoJson, Bounds bounds, String osmUrl, String fileName) {
        JSONArray jsonArray = geoJson.getJSONArray("features");
        int row = jsonArray.size();
        lonLatMap = new ConcurrentHashMap<>(row);
        for (int i = 0; i < jsonArray.size(); i++) {
            JSONObject all=jsonArray.getJSONObject(i);
            JSONArray jsonObject = all.getJSONObject("geometry").getJSONArray("coordinates");
            JSONObject properties = all.getJSONObject("properties");
            for (int j = 0; j < jsonObject.size(); j++) {
                JSONArray jsonArray1 = jsonObject.getJSONArray(j);
                String propKey = "name";
                for (int k = 0; k < jsonArray1.size(); k++) {
                    JSONArray jsonArray2 = jsonArray1.getJSONArray(k);
                    double lon = jsonArray2.getDouble(0);
                    double lat = jsonArray2.getDouble(1);
                    String key = lon + "+" + lat;
                    lonLatMap.put(key, new NodeInfo(properties.getString(propKey), indexNum.getAndIncrement(), propKey, lon, lat));
                }
            }
        }
        Document document = dataDocument(bounds);
        String xmlHeader = document.asXML();
        xmlHeader= xmlHeader.replace("</osm>", "");
        writerFoFileOSM(xmlHeader, osmUrl, fileName);
        document.clearContent();
        setNode(document.getRootElement(), osmUrl, fileName);
        writeWay(document.getRootElement(), osmUrl, fileName,jsonArray);
        BufferedWriter bufferedWriter = CommWriterFileInfo.getWriterBuffer(osmUrl + "\\" + fileName, true);
        CommWriterFileInfo.writer(bufferedWriter, "</osm>");
    }

    private static void writeWay(Element rootElement, String osmUrl, String fileName,JSONArray jsonArray) {
        int row = jsonArray.size();
        BufferedWriter bufferedWriter = CommWriterFileInfo.getWriterBuffer(osmUrl + "\\" + fileName, true);
        for (int i = 0; i < row; i++) {
            JSONObject jsonObject = jsonArray.getJSONObject(i);
            JSONObject geometry = jsonObject.getJSONObject("geometry");
            JSONObject jsonObject1=jsonObject.getJSONObject("properties");
            String path = jsonObject1.getString("path");
            Element element = setWay(rootElement, geometry.getJSONArray("coordinates"), jsonObject1, i);
            if (element == null){
                continue;
            }
//            setWayElement(element,path);
            CommWriterFileInfo.writer(bufferedWriter, element.asXML());
            System.out.println(row+ " way:" + i+"  " + element.asXML());
        }
    }

    private static void setWayElement(Element element,String path) {
            //水路
            if (path != null && path.contains("segments_with_ports.geojson")){
                Element tagRoadType = element.addElement("tag");
                tagRoadType.addAttribute("k", "route");
                tagRoadType.addAttribute("v", "ferry");
            }
    }

    private static Map<String,Object> setOSMDataProperties(JSONObject properties) {
        Map<String,Object> dataValue=new HashMap<>();
        if (properties != null){
            String path=properties.getString("path");

            //水路
            if (path != null && path.contains("segments_with_ports.geojson")){
                dataValue.put("name", properties.get("start_port"));
//                dataValue.put("waterway","navigation");
                dataValue.put("max_speed", "40");
                dataValue.put("highway", "motorway");
            //铁路
            }else {
                dataValue.put("railway","rail");
                dataValue.put("max_speed", "80");
                dataValue.put("highway", "motorway");
            }

            properties.remove("path");
            properties.remove("start_port");
            properties.remove("end_port");
            properties.remove("osm_id");
            properties.remove("kind");
            properties.remove("code");
            properties.remove("fclass");
            properties.remove("layer");
            properties.remove("bridge");
            properties.remove("tunnel");
            properties.remove("id");
        }
        return dataValue;
    }

    public static void writerFoFileOSM(String data, String folderPath, String fileName) {
        try {
            File folder = new File(folderPath);
            if (!folder.exists()) {
                folder.mkdirs();
            }
            BufferedWriter bufferedWriter = CommWriterFileInfo.getWriterBuffer(folderPath + "\\" + fileName, false);
            CommWriterFileInfo.writer(bufferedWriter, data);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static final ExecutorService executor = Executors.newFixedThreadPool(50); // 使用固定大小的线程池，大小根据实际情况调整

    public static void setNode(Element osm, String folderPath, String fileName) {
        // 使用 BufferedWriter 来写入文件
        try (BufferedWriter bufferedWriter = CommWriterFileInfo.getWriterBuffer(folderPath + File.separator + fileName, true)) {
            long row = lonLatMap.size();
            long i = 0;

            // 提交每个节点处理任务给线程池
            List<Callable<Void>> tasks = new ArrayList<>();
            for (Map.Entry<String, NodeInfo> node : lonLatMap.entrySet()) {
                final long index = i;
                tasks.add(() -> {
                    Element element1 = setNodeElement(osm, node.getValue());
                    String xml = element1.asXML();
                    synchronized (bufferedWriter) {  // 确保写入操作是线程安全的
                        CommWriterFileInfo.writer(bufferedWriter, xml);
                    }
                    System.out.println(row + " node: " + index + " " + xml);
                    return null;
                });
                i++;
            }

            // 执行所有任务
            List<Future<Void>> futures = executor.invokeAll(tasks);
            for (Future<Void> future : futures) {
                future.get(); // 确保任务完成
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static Element setNodeElement(Element osm, NodeInfo nodeInfo) {
        Element node1 = DocumentHelper.createElement("node");
        node1.addAttribute("id", nodeInfo.getIndex() + "");
        node1.addAttribute("visible", true + "");
        node1.addAttribute("version", 1 + "");
        node1.addAttribute("lat", nodeInfo.getY() + "");
        node1.addAttribute("lon", nodeInfo.getX() + "");
        Element tagRoadType = node1.addElement("tag");
        tagRoadType.addAttribute("k", "railway");
        tagRoadType.addAttribute("v", "stop");

        Element tagRoadType2 = node1.addElement("tag");
        tagRoadType2.addAttribute("k", "subway");
        tagRoadType2.addAttribute("v", "yes");

        Element tagRoadType3 = node1.addElement("tag");
        tagRoadType3.addAttribute("k", "name");
        tagRoadType3.addAttribute("v", fetchLocationName(nodeInfo.getY(), nodeInfo.getX()));
        return node1;
    }

    public static Document dataDocument(Bounds bounds) {
        Document document = DocumentHelper.createDocument();
        Element osm = document.addElement("osm");
        osm.addAttribute("version", "0.6");
        osm.addAttribute("generator", "CGImap 0.8.8 (587855 spike-08.openstreetmap.org)");
        osm.addAttribute("copyright", "OpenStreetMap and contributors");
        osm.addAttribute("attribution", "http://www.openstreetmap.org/copyright");
        osm.addAttribute("license", "http://opendatacommons.org/licenses/odbl/1-0/");

        Element boundsEl = osm.addElement("bounds");
        boundsEl.addAttribute("minlat", bounds.getMinLat() + "");
        boundsEl.addAttribute("minlon", bounds.getMaxLon() + "");
        boundsEl.addAttribute("maxlat", bounds.getMaxLat() + "");
        boundsEl.addAttribute("maxlon", bounds.getMaxLon() + "");
        boundsEl.addAttribute("id", indexNum.getAndIncrement() + "");
        boundsEl.addAttribute("version", "1");
        return document;
    }

    private static String fetchLocationName(double lat, double lon) {

        String urlString = String.format("http://101.43.251.27:18099/search/text?ak=df263d996281d984952c07998dc54358&lat=%f&lon=%f&categories=交通", lat, lon);
//        try {
//            URL url = new URL(urlString);
//            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
//            conn.setRequestMethod("GET");
//            conn.setConnectTimeout(5000);
//            conn.setReadTimeout(5000);
//
//            if (conn.getResponseCode() == 200) {
//                String response = IOUtils.toString(conn.getInputStream(), StandardCharsets.UTF_8);
//                System.out.println(response);
//                JSONObject json = HttpUtils.get(urlString, null);
//                if(json.getInteger("status") == 0) {
//                    JSONArray results = json.getJSONArray("result");
//                    if (results != null && !results.isEmpty()) {
//                        return results.getJSONObject(0).getJSONObject("properties").getString("name");
//                    }
//                }
//            }
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
        return null;
    }

    public static Element setWay(Element osm, JSONArray lonlatList, JSONObject properties, int i) {
//        Element way = osm.addElement("way");
        Element way = DocumentHelper.createElement("way");
        way.addAttribute("id", indexNum.getAndIncrement() + "");
        way.addAttribute("visible", true + "");
        way.addAttribute("version", 1 + "");
        int lonlatSize = lonlatList.size();
        String path=properties.getString("path");
        if (path == null){
            return null;
        }
        for (int j = 0; j < lonlatSize; j++) {


            JSONArray point = lonlatList.getJSONArray(j);
            for (int k = 0; k < point.size(); k++) {
                JSONArray point1 = point.getJSONArray(k);
                double lon = point1.getDouble(0);
                double lat = point1.getDouble(1);
                String key = lon + "+" + lat;
                Element nod = way.addElement("nd");
                NodeInfo nodeInfo = lonLatMap.get(key);
                nod.addAttribute("ref", nodeInfo.getIndex() + "");
            }

        }

        if (properties != null) {
            Set<String> keys = properties.keySet();
            Iterator<String> iterator = keys.iterator();
            while (iterator.hasNext()) {
                String key = iterator.next();
                String o = properties.getString(key);
                Element tagName = way.addElement("tag");
                tagName.addAttribute("k", key);
                tagName.addAttribute("v", o);
            }
          Map<String, Object> dataValue = setOSMDataProperties(properties);    setOSMDataProperties(properties);
            if (dataValue != null){
                for (Map.Entry<String, Object> entry : dataValue.entrySet()){
                    Element tagName = way.addElement("tag");
                    tagName.addAttribute("k", entry.getKey());
                    tagName.addAttribute("v", entry.getValue()+"");
                }
            }
//            Element tagRoadType = way.addElement("tag");
//            tagRoadType.addAttribute("k", "highway");
//            tagRoadType.addAttribute("v", "motorway");
        }
        return way;
    }
}
